package cn.persistenceCollection.fileBasedImpl

import cn.persistenceCollection.*
import com.easy.server.persistenceCollection.*
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit


abstract class AbstractFilePersistenceCollection(
    filePath: String,
    var initCap: Int = 16,
    fileMapperType: FileMapperType = FileMapperType.MergedMemoryMapMapper,
    val flushPerOption: Boolean,//是否每个操作都及时刷盘
    val flushIntervalMills: Long, //当flushPerOption=false时 定时刷盘的间隔
    val context: PersistenceContext
) : FilePersistenceCollection {
    var fileMapper: FileMapper
    private val initFileSize = 1024 * 1024L
    private var closed: Boolean = false

    var fileSize: Long
        get() = fileMapper.fileSize
        set(value) {
            fileMapper.fileSize = value
        }

    init {
        //fileMapper = MemoryMapMapper(filePath, initFileSize)
        fileMapper = when (fileMapperType) {
            FileMapperType.MemoryMapMapper -> MemoryMapMapper(filePath, initFileSize)
            FileMapperType.RandomAccessFileMapper -> RandomAccessFileMapper(filePath, initFileSize)
            FileMapperType.MergedMemoryMapMapper -> MergedMemoryMapMapper(filePath, initFileSize)
        }

        context.register(this)

    }

    override fun closed(): Boolean {
        return closed
    }

    override fun flush() {
        fileMapper.force()
    }

    @Synchronized
    override fun close() {

        context.unregister(this)
        fileMapper.force()
        fileMapper.close()
        closed = true
    }

    fun resizeFile(magnification: Int = 2) {
        fileSize *= magnification
    }

    /**
     * 分配新的空间，返回空间的起始位置
     */
    fun alloc(size: Long): Long {


        val start = usageFileSize

        while (start + size >= fileSize) {

            resizeFile()
        }

        usageFileSize = start + size


        return start
    }


    abstract var usageFileSize: Long

    abstract var cap: Int

    abstract var indexArrayPosition: Long


    abstract val indexArray: IndexArray<out Any>

    abstract inner class IndexArray<T>(val position: Long, val cap: Int) {
        abstract operator fun get(index: Int): T
    }
    /**
     * 压缩文件
     * return 压缩了多少bytes
     */
    abstract fun compress(): Long
    /**
     *
     * 扩张容量
     */
    protected abstract fun expansion(newCap: Int)
    /**
     * 获取索引数组容量
     *
     */
    protected abstract fun computeIndexArraySize(cap: Int): Long
}